<?php
/**
 * MyReceiveMailBean.class.php
 * 
 * (C) 2009, tetsuya.odaka(EzoGP).
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* 
 * POP3サーバーからメイルを受信するオブジェクト
 *  (a) コンストラクタに渡す引数
 *       ホスト（アドレス）
 *       ポートNo
 *       受信ユーザー
 *       受信ユーザーのパスワード
 *       受信後にメッセージを削除するたどうか（true/false）
 *  (b) 結果
 *     <メイルが取得できたとき>
 *       from => 送信者のメイルアドレス
 *       date => 受信時間   yyyy-mm-dd HH:MM:SS
 *       subject => 件名
 *       body => 本文
 *     <メイルが取得できなかったとき>
 *       false (boolean)
 *  
 *  （注）
 *  multipartメッセージの場合、application、image部（添付）は../tmp/下に書き出されるため、
 *  書き込み権限を与えてください。
 *  添付ファイル名はurlencodingされます。
 *  
 *  （既知の問題）
 *  添付ファイルがtxt形式の場合、本文を間違ってしまう。
 *  
 * dependencies: PEAR::Net_Pop3, Mail_MimeDecode
 * 
 * author	；  t.odaka
 * date		; 2009/5/16
 * modified ; 2009/11/10 t.odaka
 *            ホスト名などをconstructorの引数に持たせる。
 *            single partのbody部がsubjectになっていたbugのfix。
 *            delMsgができないbugのfix。
 * 
 * 			  2009/11/26 t.odaka
 *            Mailが取得できなかったとき、戻り値にfalse(boolean)を設定する。
 *            Config.phpのinclude_pathにMyznalaをいれたことによるプログラムパス調整
 *            
 *            2009/11/27 t.odaka
 *            mail headerを解析した結果を加工せず、timestampで戻すようにした。
 *            汎用性を確保するため。
 * 
*/

// 2009/11/26 t.odaka 
require_once('Config.php');

require_once("Net/POP3.php");
require_once('Mail/mimeDecode.php');

class MyReceiveMailBean {
	/* プロパティー */
	var $_Pop3host, $_Pop3port, $_Pop3user, 
		$_Pop3pass, $_Pop3DeleteAfter; 
	
	/* 
	 * デフォルトのコンストラクタ 
	 * 
	 *  Config.phpからPOPサーバーへの接続定義を取得する。
	 */
/*
	function __construct() {
		
		require("../Myznala/debugLog.php");
		// debugログの出力
//		$myDebugLog->debug("constructor: start");
		$this->setPop3Host();
		$this->setPop3Port();
		$this->setPop3User();
		$this->setPop3Pass();
		$this->setPop3DeleteAfter();
		// debugログの出力
//		$myDebugLog->debug("constructor: end");
	}
*/
	
	/* コンストラクタ */
	function __construct($pop3Host, 
				$pop3Port, $pop3User,
				$pop3Pass, $pop3DelAft) {
		
		// 2009/11/26 t.odaka 
		require("debugLog.php");
		// debugログの出力
//		$myDebugLog->debug("constructor: start");
		$this->_Pop3host = $pop3Host;
		$this->_Pop3port = $pop3Port;
		$this->_Pop3user = $pop3User;
		$this->_Pop3pass = $pop3Pass;
		$this->_Pop3DeleteAfter = $pop3DelAft;
		
		// debugログの出力
//		$myDebugLog->debug("constructor: end");
	}
	
	/* setter */
/*	function setPop3Host(){
		$this->_Pop3host=POP3HOST;
	}
	function setPop3Port(){
		$this->_Pop3port=POP3PORT;
	}
	function setPop3User(){
		$this->_Pop3user=POP3USER;
	}
	function setPop3Pass(){
		$this->_Pop3pass=POP3PASS;
	}
	function setPop3DeleteAfter(){
		$this->_Pop3DeleteAfter=POP3DELETEAFTER;
	}
*/
	
	function mailReceive(){
		// 2009/11/26 t.odaka 
		require("debugLog.php");
		
		// debguログの出力
//		$myDebugLog->debug("mailreceive: start");

		/*
		 * 変数定義
		 */
		$host=$this->_Pop3host;
    	$port=$this->_Pop3port;
    	$user=$this->_Pop3user;
		$pass=$this->_Pop3pass;
		$delaft=$this->_Pop3DeleteAfter;
		
//		$myDebugLog->debug("host: ".$host);
//		$myDebugLog->debug("port: ".$port);
//		$myDebugLog->debug("user: ".$user);
//		$myDebugLog->debug("pass: ".$pass);
//		if($delaft){
//			$myDebugLog->debug("delete_after: true");
//		}else{
//			$myDebugLog->debug("delete_after: false");
//		}
    	/*
    	 * ログイン
    	 */
		$pop3 = new Net_POP3();
		$ret = $pop3->connect($host, $port);

		// 接続OKのとき
		if ($ret) {
			$myDebugLog->debug("connected to ".$host);
			
			// trueにするとAPOPを見に行くので、止めた方がいいかもしれない。
			$ret = $pop3->login($user, $pass);
			//$ret = $pop3->login($user, $pass, true);
			// ログインOKのとき
		    if ($ret) {
				$myDebugLog->debug("logged in to ".$host);
			
		        $cnt = $pop3->numMsg();
				$myDebugLog->debug("num of messages ".$cnt);

				for ($i=1; $i <= $cnt; $i++) {
					$msg = array();  
					$attach = array();
				
					//メールをMail_mimeDecodeでパースする  
					$dObj = new Mail_mimeDecode($pop3->getMsg($i));
					
					$params['include_bodies'] = true; //ボディを解析する  
					$params['decode_bodies'] = true; //ボディのデコードをする   
					$params['decode_headers'] = true; //ヘッダーのデコードをする  
					// パース
					$parsedMessages = $dObj->decode($params);  
//					$myDebugLog->debug($parsedMessages); // これで構造が全部分かるよ！！
				
					/*
					 * ヘッダーの処理
					 */
					//送信者のメールアドレスを抽出  
					$from = $parsedMessages->headers['from'];  
//					$myDebugLog->debug('$from: '.$from);
					
					//署名付きのアドレスの場合、そちらを優先する。  
					preg_match("/<.*>/", $from, $str);  
					if ($str[0]!="") {  
						$str = substr($str[0], 1, strlen($str[0])-2);  
						$from = $str;  
					}  
//					$myDebugLog->debug('$from: '.$from);
					$msg['from'] = $from;
					
					// 受信時間を取得 
					if($parsedMessages->headers['date'] == null){
					// 普通にdateヘッダーがない場合（$parsedMessagesをダンプして対応してください）。
					// 以下、XMailServerの場合
//						$myDebugLog->debug('$date: '.$parsedMessages->headers['received']);
						$wk = split(";",$parsedMessages->headers['received']);
//						$myDebugLog->debug('orgTime: '.$wk[1]);
						// 2009/11/27 t.odaka
						// 汎用性を確保するため、ここでは加工せず、timestampだけとることにする。
						$date = strtotime($wk[1]);
//						$date = date("Y-m-d H:i:s", strtotime($wk[1]));
						$msg['date'] = $date;	
					}else{
					// 普通にdateヘッダーがある場合。
					// 以下、BlackJumboDogの場合
//						$myDebugLog->debug('$date: '.$parsedMessages->headers['date']);
						// 2009/11/27 t.odaka
						// 汎用性を確保するため、ここでは加工せず、timestampだけとることにする。
						$date = strtotime($parsedMessages->headers['date']);
//						$date = date("Y-m-d H:i:s", strtotime($parsedMessages->headers['date']));
						$msg['date'] = $date;					
					}
					
					// 件名を取得  
					$subject = $parsedMessages->headers['subject'];  
					$subject = mb_convert_encoding($subject, "UTF-8", "jis");  
//					$myDebugLog->debug('$subject: '.$subject);
					$msg['subject'] = $subject;
					
					/*
					 * パート（本文、添付）の処理
					 */
					switch(strtolower($parsedMessages->ctype_primary)){  
  
						// シングルパート(本文のみ)
						case "text":
							$body = $parsedMessages->body;  
							$body = mb_convert_encoding($body, "UTF-8", "jis");  
//							$myDebugLog->debug('Single Part Message');
//							$myDebugLog->debug('$body: '.$body);
							$msg['body'] = $body;
							// attachmentはnull.
							$msg['attachment'] = null;
							break;  
  
						// マルチパート
						// 各パートを１つのメイルとして処理する。  
						case "multipart":
//							$myDebugLog->debug('Multi Part Message');
							foreach($parsedMessages->parts as $part){
							
								switch(strtolower($part->ctype_primary)){  
  
								// 本文  
								case 'text':
									$body = $part->body;  
									$body = mb_convert_encoding($body, "UTF-8", "jis");  
//									$myDebugLog->debug('Contents');
//									$myDebugLog->debug('$body: '.$body);
									$msg['body'] = $body;
									break;
  
								// バイナリー(application file)
								case 'application':
									//添付ファイル
									foreach($part->ctype_parameters as $key => $value ){
										//ISO-2022-JPの場合
										if($key == 'name'){
											$fName = mb_convert_encoding($value, "UTF-8", "jis"); 
										}else{
											//US-ASCIIの場合
//												$myDebugLog->debug('$value: '.$value);
												$ret = preg_replace('/^(US-ASCII\'\')+?/', '', $value);
//												$myDebugLog->debug('$ret: '.$ret);
												//長い日本語名称の場合の対応
												$ret1 = preg_replace('/(\"\s(name)\*\d\*=\")+/','',$ret);
//												$myDebugLog->debug('$ret1: '.$ret1);
												$fName = urldecode($ret1);
										}
									}
										
									//ファイル名がsjisであると過程して、UTF-8から変換（復元）する。
									$sjisfName = mb_convert_encoding($fName, "Shift-JIS", "UTF-8"); 
										
//									$myDebugLog->debug('$sjisfName: '.$sjisfName);
								
									// 画面用配列
									$n = count($attach);
									$attach[$n] = array($fName,urlencode($fName)); // 画面表示用なのでUTF-8のものを格納
																	
									// 添付ファイル(body部)を書き出す（ファイル名はOSのエンコーディングにあわせる）。
//									$osfName = mb_convert_encoding($sjisfName,OS_ENCODING,"Shift-JIS");
//									$myDebugLog->debug('$osfName: '.$osfName);
									// URL Encodeしたファイル名で保存
									$fp = fopen('../tmp/'.urlencode($fName), "w");
//									$fp = fopen('../tmp/'.$osfName, "w");  
									//$fp = fopen('../tmp/'.$fName, "w");  
									$length = strlen($part->body);
									fwrite($fp, $part->body, $length);  
									fclose($fp);
									break;  
  
								// バイナリー(image file)
								case "image":
									foreach($part->ctype_parameters as $key => $value ){
										//ファイル名が、US-ASCIIの場合
										preg_match('/^(US-ASCII\'\')+?/',$value,$match);
										if($match[0].length > 0){
//												$myDebugLog->debug('$value: '.$value);
												$ret = preg_replace('/^(US-ASCII\'\')+?/', '', $value);
//												$myDebugLog->debug('$ret: '.$ret);
												//長い日本語名称の場合の対応
												$ret1 = preg_replace('/(\"\s(name)\*\d\*=\")+/','',$ret);
//												$myDebugLog->debug('$ret1: '.$ret1);
												$fName = urldecode($ret1);
																														
										}else{
											//ISO-2022-JPの場合
											if($key == 'name'){
												$fName = mb_convert_encoding($value, "UTF-8", "jis"); 
											}
										} 
									}
										
									//ファイル名がsjisであると過程して、UTF-8から変換（復元）する。
									$sjisfName = mb_convert_encoding($fName, "Shift-JIS", "UTF-8"); 
//									$myDebugLog->debug('$sjisfName: '.$sjisfName);
								
									// attachmentはファイル名を配列にいれていく。
									$n = count($attach);
									$attach[$n] = array($fName,urlencode($fName)); // 画面表示用なのでUTF-8のものを格納
																	
									// 添付ファイル(body部)を書き出す（ファイル名はOSのエンコーディングにあわせる）。
//									$osfName = mb_convert_encoding($sjisfName,OS_ENCODING,"Shift-JIS");
//									$myDebugLog->debug('$osfName: '.$osfName);
//									if(strtolower(OS_ENCODING) == 'shift_jis'){
									// URL Encodeした名前で保存
									$fp = fopen('../tmp/'.urlencode($fName), "w");
//										$fp = fopen('../tmp/'.$osfName, "w");
//									}else{
//										$fp = fopen('../tmp/'.$fName, "w");
//									}  
									$length = strlen($part->body);
									fwrite($fp, $part->body, $length);  
									fclose($fp);
									break;  

								default:
								
								}
							} // partのloopの終了
							
							$msg['attachment'] = $attach;
							
							break;
						
						// シングルパートとマルチパート以外。（基本的にはない）
						default:
						$body = "";  
					}
					$result[$i]=$msg;
			
					// メッセージの削除
       				if($delaft){
						$delresult = $pop3->deleteMsg($i);
						if($delresult){
							$myDebugLog->debug("success; delete msg".$i);
						}else{
							$myDebugLog->debug("failure; delete msg".$i);
						}
       				}
				}
			
				// 取得した結果（$result）を日付降順でソート
				if(count($result)>0){
					$darray = array();
					foreach($result as $v) array_push($darray,$v['date']); //sort用配列
					array_multisort($darray, SORT_DESC, SORT_STRING, $result);
				}
               		
   	 		} else {
        		return false;
    		}
		} else {
        	return false;
	}
	// 切断
	$pop3->disconnect();
	
	// t.odaka 2009/11/26
	if(is_array($result)){
	}else{
		$result = false;
	}
	
	return $result;
	}
}
?>